package org.wabson.alfresco.translations;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.wabson.alfresco.translations.bean.BundlePackage;
import org.wabson.alfresco.translations.bean.JarListLoader;
import org.wabson.alfresco.translations.bean.Jarfile;
import org.wabson.alfresco.translations.bean.PackageCollection;
import org.wabson.alfresco.translations.bean.Version;
import org.wabson.alfresco.translations.bean.VersionCollection;

public class BundleDetailsServlet extends HttpServlet
{
    public static final String BLOB_KEY_PARAM_NAME = "k";
    public static final String JAR_FILE_PARAM_NAME = "j";
    public static final String MESSAGE_BUNDLE_SUFFIX_PARAM_NAME = "s";

    /**
     * 
     */
    private static final long serialVersionUID = -8257907161559122261L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
    	WebApplicationContext springContext = WebApplicationContextUtils
    			.getRequiredWebApplicationContext(getServletContext());
    	
        String blobKeyName = req.getParameter(BLOB_KEY_PARAM_NAME);
        String jarName = req.getParameter(JAR_FILE_PARAM_NAME);
        String suffix = req.getParameter(MESSAGE_BUNDLE_SUFFIX_PARAM_NAME);
        
        resp.setContentType("text/html; charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        if ((blobKeyName == null || blobKeyName.equals("")) && (jarName == null || jarName.equals("")))
        {
            throw new ServletException("No blob key was specified");
        }
        
        // Fetch the file name or the uploaded JAR/AMP
        String fileName = "";
        String creationDate = "";
        long size = 0L;
        
        if (blobKeyName != null)
        {
        	Jarfile jar = ((JarListLoader) springContext.getBean("jar-list-loader")).getJar(blobKeyName);
            
            if (jar == null)
            {
                throw new ServletException("Could not find information on blob " + 
                        blobKeyName + ". Does it exist?");
            }
            else
            {
                fileName = jar.getName();
                creationDate = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(jar.getCreationDate());
                size = jar.getSize();
            }
        }
        else
        {
            fileName = jarName;

            if (!jarName.endsWith(".jar"))
            {
                throw new ServletException("Package name must end with .jar suffix");
            }
        }

        if (suffix == null || suffix.equals(""))
        {
            // Attempt to guess suffix from file name
            if (fileName.matches("^[-\\w\\._]+[-_][a-z]{2}_[A-Z]{2}\\.[\\w]+$"))
            {
                suffix = fileName.substring(fileName.lastIndexOf('.') - 5, fileName.lastIndexOf('.'));
            }
            else if (fileName.matches("^[-\\w\\._]+[-_][a-z]{2}\\.[\\w]+$"))
            {
                suffix = fileName.substring(fileName.lastIndexOf('.') - 2, fileName.lastIndexOf('.'));
            }
        }
        if (suffix != null && !suffix.equals("") && !suffix.startsWith("_"))
        {
            suffix = "_" + suffix;
        }
        if (suffix == null)
        {
            suffix = "";
        }
        
        String messagesPath = (fileName.endsWith(".amp")) ? "config" :"";
        BundleLoader loader = null;
        
        try
        {
            if (blobKeyName != null)
            {
                loader = ((BundleLoaderFactory) springContext.getBean("langpack-loader-factory")).createLoader(blobKeyName, messagesPath);
            }
            else
            {
                loader = ((BundleLoaderFactory) springContext.getBean("bundle-loader-factory")).createLoader(jarName, messagesPath);
            }
        }
        catch (BundleLoadingException e)
        {
            throw new ServletException("Unable to load package", e);
        }
        catch (IllegalArgumentException e)
        {
            // Do nothing;
        }
        
        Set<String> files = loader != null ? loader.getFiles() : null;
        
        PrintWriter out = resp.getWriter();
        
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Package " + fileName + "</title>\r\n");
        out.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/screen.css\" />");
        out.println("</head>");
        out.println("<body>");
        out.println("<div class=\"header\">");
        out.println("<p class=\"title\"><a href=\"/\">Alfresco I18N Tools</a></p>");
        out.println("</div>");
        out.println("<div class=\"body\">");
        out.println("<h1>Package " + fileName + "</h1>");
        if (loader != null)
        {
	        if (!creationDate.equals(""))
	            out.println("<p><strong>Uploaded:</strong> " + creationDate + "<br />");
	        out.println("<strong>Contains:</strong> <a href=\"#filelist\">" + loader.getNumFiles() + " files</a><br />");
	        if (size != 0L)
	            out.println("<strong>Size:</strong> " + NumberFormat.getInstance().format(size) + " bytes</p>");
        }
        if (blobKeyName != null)
        {
            Pattern versionPattern = Pattern.compile("(?:community|enterprise)[\\-_][A-Za-z0-9\\.]+");
        	// Try to autodetect the translation version from the filename
        	String tv = "";
        	Matcher m = versionPattern.matcher(fileName);
        	if (m.find(0));
        	{
        	    try
        	    {
            		tv = m.group();
        	    }
        	    catch (IllegalStateException e)
        	    {
        	        // Do nothing
        	    }
        	}
            out.println("<p><a href=\"/download?k=" + blobKeyName + "\">Download package</a></p>");
            out.println("<div class=\"results\">");
            out.println("<h2>Score Translation</h2>");
            out.println("<p>Score the completeness of the translation against the base (US English) package.</p>");
            out.println("<form action=\"/compare\" method=\"get\">");
            out.println("<div class=\"form-field\">");
            out.println("Compare translation <strong>" + fileName + "</strong> (using <span style=\"border-bottom: 1px dashed #333333;\" title=\"e.g. _en, _fr_CA. If left blank will be taken from file name.\">file suffix</span> ");
            out.println("<input id=\"suffix\" type=\"text\" name=\"s\" size=\"6\" value=\"" + suffix + "\" />");
            out.println(")</div>");
            out.println("<div class=\"form-field\">");
            out.println("With base package <select id=\"version\" name=\"v\">");
            VersionCollection vc = (VersionCollection) springContext.getBean("alfresco-versions");
            List<Version> versions = vc.getVersions();
            for (Version version : versions)
            {
            	out.println("<option value=\"" + version.getName() + "\"" + (version.getName().equalsIgnoreCase(tv) ? " selected=\"selected\"" : "") + ">" + version.getTitle() + "</option>");
			}
            out.println("</select>, ");
            out.println("<select id=\"package\" name=\"p\">");
            PackageCollection pc = (PackageCollection) springContext.getBean("alfresco-packages");
            List<BundlePackage> packages = pc.getPackages();
            for (BundlePackage p : packages)
            {
            	out.println("<option value=\"" + p.getName() + "\"" + (fileName.startsWith(p.getName()) ? " selected=\"selected\"" : "") + ">" + p.getTitle() + "</option>");
			}
            out.println("</select>");
            out.println("</div>");
            out.println("<div class=\"form-field\">");
            out.println("<input type=\"hidden\" name=\"k\" value=\"" + blobKeyName + "\">");
            out.println("<input type=\"submit\" value=\"Compare\">");
            out.println("</div>");
            out.println("</form>");
            out.println("</div>");
        }
        else
        {
        	if (loader != null)
        	{
        		// Get package name. Core is empty package name, others are 1 or two parts of the JAR name (repostory, vti-module)
        		String pkg = "";
	            String[] baseCmpts = jarName.substring(0, jarName.length() - 4).split("-"); // Remove .jar suffix and split on ,
	            for (int i=2; baseCmpts.length > i+2; i++)
	            	pkg = pkg + (pkg != "" ? "-" : "") + baseCmpts[i];
	            
	            // May be alfresco-community-messages-3.3.jar or alfresco-community-repository-messages-3.3.jar (4 or 5 parts)
	            String baseVersion = baseCmpts[1] + "-" + baseCmpts[baseCmpts.length-1];
	            out.println("<p><a href=\"/download?j=" + jarName + "\">Download package</a></p>");
	            out.println("<h2>Message Bundle Changes (Experimental)</h2>");
	            out.println("<p>Find out what message bundles have changed between Alfresco versions</p>");
	            out.println("<form action=\"/changes\" method=\"get\">");
	            out.println("<div class=\"form-field\">");
	            out.println("Compare with ");
	            out.println("<select id=\"compareVersion\" name=\"c\">");
	            VersionCollection vc = (VersionCollection) springContext.getBean("alfresco-versions");
	            List<Version> versions = vc.getVersions();
	            for (Version version : versions)
	            {
	            	out.println("<option value=\"" + version.getName() + "\">" + version.getTitle() + "</option>");
				}
	            out.println("</select>");
	            out.println("<span class=\"form-help\"></span></div>");
	            out.println("<div class=\"form-field\">");
	            out.println("<input name=\"b\" value=\"" + baseVersion + "\" type=\"hidden\">");
	            out.println("<input name=\"p\" value=\"" + pkg + "\" type=\"hidden\">");
	            out.println("<input value=\"Compare\" type=\"submit\">");
	            out.println("</div>");
	            out.println("</form>");
        	}
        	else
        	{
        		out.println("<p>The bundle was not found. Perhaps the package does not exist in the version selected (e.g. the Mobile package is not available in Enterprise versions)</p>");
        	}
        }
        if (files != null)
        {
	        out.println("<a name=\"filelist\"><h2>File List</h2>");
	        out.println("<p>");
	        for (String f : files)
	        {
	            if (blobKeyName != null)
	            {
	                out.println("<a href=\"/bundle?k=" + blobKeyName + "&f=" + messagesPath + f + "\">" + f + "</a><br />");
	            }
	            else
	            {
	                out.println("<a href=\"/bundle?j=" + jarName + "&f=" + messagesPath + f + "\">" + f + "</a><br />");
	            }
	        }
	        out.println("</p>");
        }
        
        out.println("</div>");
        out.println("</body>");
        out.println("</html>");
    }
    
}
